package com.starblink.android.basic.appsflyer

import android.content.Context
import android.net.Uri
import com.adjust.sdk.Adjust
import com.adjust.sdk.AdjustEvent
import com.appsflyer.AppsFlyerConversionListener
import com.appsflyer.AppsFlyerLib
import com.appsflyer.attribution.AppsFlyerRequestListener
import com.appsflyer.deeplink.DeepLink
import com.appsflyer.deeplink.DeepLinkListener
import com.appsflyer.deeplink.DeepLinkResult
import com.google.android.gms.ads.identifier.AdvertisingIdClient
import com.google.android.gms.common.GooglePlayServicesNotAvailableException
import com.starblink.android.basic.BuildConfig
import com.starblink.android.basic.config.showTrackLogDss
import com.starblink.android.basic.ext.getQueryParameterMap
import com.starblink.android.basic.ext.toBean
import com.starblink.android.basic.ext.toJson
import com.starblink.android.basic.sensorsdata.room.entity.SKTraceEntity
import com.starblink.android.basic.sensorsdata.room.entity.SkAntEntity
import com.starblink.android.basic.sensorsdata.spm.GTrackerAssistUtils
import com.starblink.android.basic.sensorsdata.spm.cfg.SpmElementDef
import com.starblink.android.basic.sensorsdata.spm.event.TrackEvent
import com.starblink.android.basic.sensorsdata.spm.impl.SpmTrackHandler
import com.starblink.android.basic.util.bus.FlowBus
import com.starblink.android.basic.util.bus.FlowConst
import com.starblink.basic.log.SKLogger
import com.starblink.basic.storage.SkStorage
import com.starblink.basic.util.CommUtils
import java.io.IOException


object AppsflyerManager {
    const val afDevKey = "7pLL9xsPSUCG9L6dkkUXVU"
    const val showLog = false

    /**
     * 初始化Appsflyer
     * @note 如果在Application中初始化，传ApplicationContext
     * 如果延迟初始化，在Activity中初始化，传Activity！！！
     */
    fun initAppsflyer(appContext: Context) {
        val appsflyer = AppsFlyerLib.getInstance()
        if (BuildConfig.DEBUG) {
            // Make sure you remove the following line when building to production
            appsflyer.setDebugLog(true)
            appsflyer.setMinTimeBetweenSessions(0)
        }
        appsflyer.subscribeForDeepLink(deepLinkListener)
        appsflyer.init(afDevKey, conversionListener, appContext)
        appsflyer.start(appContext, afDevKey, object : AppsFlyerRequestListener {
            override fun onSuccess() {
                SKLogger.e("dss", "appsflyer start Success", showLog)
            }

            override fun onError(p0: Int, p1: String) {
                SKLogger.e("dss", "appsflyer.start Error code=$p0, message=$p1", showLog)
            }
        })
    }

    private val conversionListener: AppsFlyerConversionListener =
        object : AppsFlyerConversionListener {
            override fun onConversionDataSuccess(conversionDataMap: MutableMap<String, Any>) {
                SKLogger.e("dss", "onConversionDataSuccess=$conversionDataMap", showLog)
                SKLogger.e("dss", "getGAID=${getGAID()}", showLog)
                //延迟上报第一次安装  //存在跨域，因为不能把点直接埋在这里
                handleFirstLaunch(conversionDataMap)
                // 测试：非自然安装
                if (conversionDataMap["af_status"]?.toString() == "Non-organic" &&
                    conversionDataMap["is_first_launch"]?.toString()?.toBoolean() == true
                ) {
                    SKLogger.e("dss", "onConversionDataSuccess: 非自然激活，首次激活", showLog)
                    val deepLinkData: DeepLink? = mapToDeepLinkObject(conversionDataMap)
                    printDeepLink(deepLinkData, "111onConversionDataSuccess/")
                }

                // 测试：reportAppAdvertLaunch
//                reportAppAdvertLaunch("And_UK_j2hundred_Spark_1126#starblinkguang://guang?ad_id=00000115&type=1")

                // 我司投放的广告
                // （1）广告链接是Appsflyer的深度链接，点击链接会回调Appsflyer的onConversionDataSuccess()方法、onDeepLinking()方法
                // （2）将deepLink值附加到campaign字段后，campaign字段含义:广告名称
                // 注意：经过测试发现，点击广告链接：如果APP未安装，安装后打开APP，仅在onConversionDataSuccess()方法参数中campaign字段有值

                // 示例：TikTok广告campaign字段值：And_UK_j2hundred_Spark_1126#starblinkguang://guang?ad_id=00000115&type=1
                // 如果campaign没有值，无需处理
                val campaign = conversionDataMap["campaign"] as? String ?: return
                SKLogger.e("dss", "campaign=${campaign}", showLog)
                val params = campaign.split("#")
                if (params.count() > 1) {
                    // 埋点：从广告启动APP
                    SKLogger.e("dss", "埋点：从广告启动APP", showLog)
                    val deepLink = params[1]
                    reportAppAdvertLaunch(deepLink)
                } else {
                    SKLogger.e("dss", "campaign字段无#后缀", showLog)
                }
            }

            override fun onConversionDataFail(errorMessage: String) {
                SKLogger.e("dss", "onConversionDataFail: $errorMessage", showLog)
            }

            override fun onAppOpenAttribution(attributionData: Map<String, String>) {
                SKLogger.e("dss", "onAppOpenAttribution: ${attributionData}", showLog)
            }

            override fun onAttributionFailure(errorMessage: String) {
                SKLogger.e("dss", "onAttributionFailure : $errorMessage", showLog)
            }
        }

    private val deepLinkListener: DeepLinkListener = object : DeepLinkListener {
        override fun onDeepLinking(deepLinkResult: DeepLinkResult) {
            when (deepLinkResult.status) {
                DeepLinkResult.Status.FOUND -> {
                    printDeepLink(deepLinkResult.deepLink, "222onDeepLinking/FOUND/")
                }

                DeepLinkResult.Status.NOT_FOUND -> {
                    printDeepLink(deepLinkResult.deepLink, "222onDeepLinking/NOT_FOUND/")
                }

                else -> {
                    SKLogger.e(
                        "dss",
                        "222onDeepLinking,dlStatus == DeepLinkResult.Status.ERROR: $deepLinkResult.error",
                        showLog
                    )
                }
            }
        }
    }


    private fun handleFirstLaunch(conversionDataMap: MutableMap<String, Any>) {
        if (conversionDataMap["is_first_launch"]?.toString()?.toBoolean() == true) {
            SKLogger.e("dss", "埋点：APP激活", showTrackLogDss)

        }
    }

    /**
     * 埋点：从广告启动APP
     */
    private fun reportAppAdvertLaunch(deepLink: String) {
        if (deepLink.isNullOrEmpty()) {
            return
        }

        val uri = Uri.parse(deepLink)
        val queryMap = uri.getQueryParameterMap()
        val map = HashMap<String, String>(queryMap)
        adid = map["ad_id"] ?: ""
        map["deeplink"] = deepLink

        SpmTrackHandler.addSingleTrackData(
            SkAntEntity(
                event = TrackEvent.appLifeCycle.value,
                spmCnt = GTrackerAssistUtils.fetchElementValue(
                    0,
                    SpmElementDef.AppAdvertLaunch
                ),
                params = map
            )
        )
    }

    /**
     * map转DeepLink对象
     */
    fun mapToDeepLinkObject(conversionDataMap: MutableMap<String, Any>): DeepLink? {
        try {
            val maps: MutableMap<String, String> = HashMap()
            conversionDataMap.forEach() {
                if (it.value == null) {
                    maps[it.key] = "null"
                } else {
                    maps[it.key] = it.value.toString()
                }
            }
            return DeepLink.AFInAppEventParameterName(maps)
        } catch (e: Exception) {
            SKLogger.e("dss", "Error when converting map to DeepLink object: $e", showLog)
        }
        return null
    }

    /**
     * 打印DeepLink对象
     */
    fun printDeepLink(deepLink: DeepLink?, prefix: String? = "") {
        if (deepLink == null) {
            SKLogger.e("dss", "${prefix}deepLinkObj == null", showLog)
            return
        } else {
            SKLogger.e("dss", "${prefix}deepLinkObj=", showLog)
            val iterator = deepLink.AFInAppEventParameterName.keys()
            while (iterator.hasNext()) {
                val key = iterator.next()
                val value = deepLink.AFInAppEventParameterName.get(key)
                SKLogger.e("dss", "key=${key}, value=${value}", showLog)
            }
        }
    }

    fun _reportEvent(event: AppsFlyerEventType, params: Map<String, Any>? = null) {
        AppsFlyerLib.getInstance()
            .logEvent(
                CommUtils.getContext(),
                event.name,
                params ?: emptyMap(),
                object : AppsFlyerRequestListener {
                    override fun onSuccess() {
                        SKLogger.e("dss", "logEvent onSuccess", showLog)
                    }

                    override fun onError(p0: Int, p1: String) {
                        SKLogger.e("dss", "logEvent， onError（code=$p0, message=$p1）", showLog)
                    }
                })
    }

    fun reportRegistration() {
        _reportEvent(
            AppsFlyerEventType.af_complete_registration,
            mapOf("af_registration_method" to "")
        )
        val adjustEvent = AdjustEvent("2egswr")
        Adjust.trackEvent(adjustEvent)
    }

    fun reportCameraRecognition() {
        _reportEvent(AppsFlyerEventType.camera_recognition)

        Adjust.trackEvent(AdjustEvent("dz4i4u"))
    }

    fun reportSearch(params: MutableMap<String, String>) {
        _reportEvent(
            AppsFlyerEventType.af_search,
            mapOf("af_search_string" to "${params["searchTerm"]}")
        )

        val adjustEvent = AdjustEvent("jq5brj")
        adjustEvent.callbackParameters = params
        Adjust.trackEvent(adjustEvent)
    }

    fun reportFollow() {
        _reportEvent(AppsFlyerEventType.user_follow)
    }

    fun reportContentClick(params: Map<String, String>) {
        _reportEvent(AppsFlyerEventType.af_content_view, params)
    }

    fun reportContentLike(params: Map<String, String>) {
        _reportEvent(AppsFlyerEventType.content_like, params)
    }

    fun reportContentComment(params: Map<String, String>) {
        _reportEvent(AppsFlyerEventType.content_comment, params)
    }

    fun reportContentShare(params: Map<String, String>) {
        _reportEvent(AppsFlyerEventType.af_share, params)

        val adjustEvent = AdjustEvent("qd9i87")
        adjustEvent.callbackParameters = params
        Adjust.trackEvent(adjustEvent)
    }

    private fun reportContentRecognition(params: Map<String, String>) {
        _reportEvent(AppsFlyerEventType.content_recognition, params)
    }

    private fun reportProductClick(params: Map<String, String>) {
        _reportEvent(AppsFlyerEventType.product_link_click, params)

        val adjustEvent = AdjustEvent("7ot0ei")
        adjustEvent.callbackParameters = params
        Adjust.trackEvent(adjustEvent)
    }

    private fun reportProductExposure(params: Map<String, String>) {
        _reportEvent(AppsFlyerEventType.product_link_show, params)

        val adjustEvent = AdjustEvent("n1fqui")
        adjustEvent.callbackParameters = params
        Adjust.trackEvent(adjustEvent)
    }

    private fun reportProductSave(params: Map<String, String>) {
        _reportEvent(AppsFlyerEventType.product_link_save, params)

        val adjustEvent = AdjustEvent("fok5od")
        adjustEvent.callbackParameters = params
        Adjust.trackEvent(adjustEvent)
    }

    /**
     * 将某些埋点上传Appsflyer
     */
    fun reportTrack(entity: SKTraceEntity) {
        if (entity.spmCnt?.contains("20001") == true
            && entity.params["productId"].isNullOrEmpty().not()
        ) {
            // 商品曝光事件和商品点击事件
            val params = mapOf(
                "product_id" to entity.params["productId"]!!,
            )
            if (entity.event == TrackEvent.elementExposure.value) {
                // 商品曝光事件
                reportProductExposure(params)
            } else if (entity.event == TrackEvent.elementClick.value) {
                // 商品点击事件
                reportProductClick(params)
            }
        } else
            if ((entity.spmCnt?.contains("30009") == true || entity.spmCnt?.contains("30133") == true || entity.spmCnt?.contains(
                    "33045"
                ) == true)
                && entity.params["productId"].isNullOrEmpty().not()
            ) {
                // 商品收藏
                val params = mapOf(
                    "product_id" to entity.params["productId"]!!,
                )
                if (entity.event == TrackEvent.elementClick.value) {
                    reportProductSave(params)
                }
            } else if ((entity.spmCnt?.contains("10017.30047") == true
                        || entity.spmCnt?.contains("10070.20030") == true)
                && entity.params["itemId"].isNullOrEmpty().not()
                && entity.params["contentType"].isNullOrEmpty().not()
            ) {
                // 内容识图事件：
                // 视频内容-识图:10017.30047
                // 图文内容-识图:10070.20030
                reportContentRecognition(
                    mapOf(
                        "af_content_id" to entity.params["itemId"]!!,
                        "af_content_type" to (entity.params["contentType"]!!),
                    )
                )
            }
    }

    private var adid = ""

    /**
     * 获取我们配置的Advertising ID
     */
    fun getADID(): String {
        return adid
    }

    private fun getGAID(): String {
        var adInfo: AdvertisingIdClient.Info? = null
        try {
            adInfo = AdvertisingIdClient.getAdvertisingIdInfo(CommUtils.getContext())
        } catch (e: IOException) {
            // Unrecoverable error connecting to Google Play services (e.g.,
            // the old version of the service doesn't support getting AdvertisingId).
            SKLogger.e("getGAID", "IOException")
        } catch (e: GooglePlayServicesNotAvailableException) {
            // Google Play services is not available entirely.
            SKLogger.e("getGAID", "GooglePlayServicesNotAvailableException")
        } catch (e: java.lang.Exception) {
            SKLogger.e("getGAID", "Exception:$e")
            // Encountered a recoverable error connecting to Google Play services.
        }
        var gaid = ""
        if (adInfo != null) {
            gaid = adInfo.id ?: ""
            SKLogger.w("getGAID", "gaid=$gaid")
        }
        return gaid
    }
}